package com.tanhua.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.*;
import com.tanhua.exception.BusinessException;
import com.tanhua.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import model.domain.Question;
import model.domain.UserInfo;
import model.dto.RecommendUserDto;
import model.mongo.RecommendUser;
import model.mongo.Visitors;
import model.vo.ErrorResult;
import model.vo.NearUserVo;
import model.vo.PageResult;
import model.vo.TodayBest;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TanhuaService {
    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Value("${tanhua.default.recommend.users}")
    private String recommendUser;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MessagesService messagesService;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    public TodayBest todayBest() {
        Long userId = UserHolder.getUserId();

        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(99d);
        }

        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());
        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);

        return todayBest;
    }


    public PageResult recommendation(RecommendUserDto recommendUserDto) {
        Long userId = UserHolder.getUserId();

        PageResult pageResult = recommendUserApi.queryRecommendUserList(
                recommendUserDto.getPage(),
                recommendUserDto.getPagesize(),
                userId);
        log.info("pageResult:" + pageResult);
        List<RecommendUser> items = (List<RecommendUser>) pageResult.getItems();
        if (items == null || items.size() == 0) {
            return pageResult;
        }

        List<Long> idList = items.stream().map(item -> {
            return item.getUserId();
        }).collect(Collectors.toList());
        log.info("idList:" + idList);
        UserInfo userInfo = new UserInfo().
                setAge(recommendUserDto.getAge()).
                setGender(recommendUserDto.getGender());

        Map<Long, UserInfo> map = userInfoApi.findByIds(idList, userInfo);
        log.info("map:" + map);
        ArrayList<TodayBest> todayBests = new ArrayList<>();
        for (RecommendUser item : items) {
            UserInfo info = map.get(item.getUserId());
            if (info != null) {
                TodayBest todayBest = TodayBest.init(info, item);
                todayBests.add(todayBest);
            }
        }
        log.info("todayBests:" + todayBests);
        pageResult.setItems(todayBests);
        return pageResult;
    }

    public TodayBest personalInfo(Long userId) {
        UserInfo userInfo = userInfoApi.findById(userId);

        RecommendUser recommendUser = recommendUserApi.queryByUserId(userId, UserHolder.getUserId());

        Visitors visitors = new Visitors()
                .setUserId(userId)
                .setVisitorUserId(UserHolder.getUserId())
                .setFrom("首页")
                .setDate(System.currentTimeMillis())
                .setVisitDate(new SimpleDateFormat("yyyyMMdd")
                        .format(new Date()))
                .setScore(recommendUser.getScore());
        visitorsApi.save(visitors);


        return TodayBest.init(userInfo, recommendUser);
    }

    public String strangerQuestions(Long userId) {
        Question question = questionApi.findByUserId(userId);
        return question == null ? "岁的法国不是大家好好VS地方就是回复v给" : question.getTxt();
    }

    public void replyQuestions(Long userId, String reply) {
        Long userIdNow = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(userIdNow);
        Map map = new HashMap<>();
        map.put("userId", userIdNow);
        map.put("huanXinId", Constants.HX_USER_PREFIX + userIdNow);
        map.put("nickname", userInfo.getNickname());
        map.put("strangerQuestion", strangerQuestions(userId));
        map.put("reply", reply);
        String message = JSON.toJSONString(map);

        Boolean aBoolean = huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId, message);
        if (!aBoolean) {
            throw new BusinessException(ErrorResult.error());
        }
    }

    public List<TodayBest> queryCardsList() {
        List<RecommendUser> recommendUsers = recommendUserApi.queryCardsList(UserHolder.getUserId(), 10);

        if (CollUtil.isEmpty(recommendUsers)) {
            String[] split = recommendUser.split(",");
            recommendUsers = new ArrayList<>();
            for (String s : split) {
                RecommendUser user = new RecommendUser();
                user.setUserId(Long.valueOf(s));
                user.setToUserId(UserHolder.getUserId());
                user.setScore(RandomUtil.randomDouble(60, 90));
                recommendUsers.add(user);
            }
        }

        List<Long> userIds = CollUtil.getFieldValues(recommendUsers, "userId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds, null);
        List<TodayBest> todayBests = new ArrayList<>();
        for (RecommendUser user : recommendUsers) {
            UserInfo userInfo = userInfoMap.get(user.getUserId());
            if (userInfo != null) {
                TodayBest todayBest = TodayBest.init(userInfo, user);
                todayBests.add(todayBest);
            }
        }
        return todayBests;
    }

    public void likeUser(Long likeUserId) {
        Boolean flag = userLikeApi.saveOrUpdate(UserHolder.getUserId(), likeUserId, true);
        if (!flag) throw new BusinessException(ErrorResult.error());

        redisTemplate.opsForSet().remove(
                Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(),
                likeUserId.toString());
        redisTemplate.opsForSet().add(
                Constants.USER_LIKE_KEY + UserHolder.getUserId(),
                likeUserId.toString());

        if (isLike(likeUserId, UserHolder.getUserId())) {
            messagesService.contacts(likeUserId);
        }
    }

    public void notLikeUser(Long likeUserId) {
        Boolean flag = userLikeApi.saveOrUpdate(UserHolder.getUserId(), likeUserId, true);
        if (!flag) throw new BusinessException(ErrorResult.error());

        redisTemplate.opsForSet().add(
                Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(),
                likeUserId.toString());
        redisTemplate.opsForSet().remove(
                Constants.USER_LIKE_KEY + UserHolder.getUserId(),
                likeUserId.toString());

        //3. 判断是否双向喜欢，删除好友(各位自行实现)
    }

    private boolean isLike(Long likeUserId, Long userId) {
        String key = Constants.USER_LIKE_KEY + userId;
        return redisTemplate.opsForSet().isMember(key, likeUserId.toString());
    }

    public List<NearUserVo> queryNearUser(String gender, String distance) {
        List<Long> userIdList = userLocationApi.queryNearUser(UserHolder.getUserId(), Double.valueOf(distance));

        if (CollUtil.isEmpty(userIdList)) {
            return new ArrayList<>();
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIdList, userInfo);

        List<NearUserVo> nearUserVos = new ArrayList<>();
        for (Long userId : userIdList) {
            if (userId == UserHolder.getUserId()) {
                continue;
            }
            UserInfo info = map.get(userId);
            if (info != null) {
                nearUserVos.add(NearUserVo.init(info));
            }
        }
        return nearUserVos;
    }
}
